package org.msn.gui.controller;

import lombok.SneakyThrows;
import org.msn.gui.init.ParentInit;

import javax.sound.sampled.*;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.URL;
import java.util.ResourceBundle;

public class OtherSoundController extends ParentInit {
    public volatile static boolean stop = false;

    @Override
    public void initialize(URL url, ResourceBundle resourceBundle) {
        new OtherSoundThread().start();
    }

    public class OtherSoundThread extends Thread {
        @SneakyThrows
        @Override
        public void run() {
            DatagramSocket datagramSocket = new DatagramSocket(Integer.parseInt(
                    ctx.channel().localAddress().toString().split(":")[1]));

            AudioFormat audioFormat = getAudioFormat();
            DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);
            SourceDataLine sourceDataLine = (SourceDataLine) AudioSystem.getLine(info);
            sourceDataLine.open(audioFormat);
            sourceDataLine.start();

            try {
                while (stop) {
                    byte[] bytes = new byte[10240];
                    DatagramPacket datagramPacket = new DatagramPacket(bytes, 10240);
                    datagramSocket.receive(datagramPacket);

                    ByteArrayInputStream byteArrayInputStream =
                            new ByteArrayInputStream(datagramPacket.getData());

                    AudioInputStream audioInputStream = new AudioInputStream(
                            byteArrayInputStream,
                            audioFormat,
                            bytes.length / audioFormat.getFrameSize()
                    );

                    playSound(audioInputStream, sourceDataLine);
                }
            } finally {
                sourceDataLine.drain();
                sourceDataLine.close();
            }
        }

        private AudioFormat getAudioFormat() {
            AudioFormat.Encoding encoding = AudioFormat.Encoding.PCM_SIGNED;
            float rate = 8000f;
            int sampleSize = 16;
            boolean bigEndian = true;
            int channels = 1;

            return new AudioFormat(encoding,
                    rate,
                    sampleSize,
                    channels,
                    (sampleSize / 8) * channels,
                    rate,
                    bigEndian);
        }

        private void playSound(AudioInputStream audioInputStream, SourceDataLine sourceDataLine) throws IOException {
            int cnt;

            byte[] bytes = new byte[10240];
            while ((cnt = audioInputStream.read(bytes, 0, bytes.length)) != -1) {
                sourceDataLine.write(bytes, 0, cnt);
            }
        }
    }
}
